package com.sali.asyncollection.controller.asyn_request_merge;

import cn.hutool.json.JSONObject;
import com.sali.asyncollection.model.BannerDTO;
import com.sali.asyncollection.model.BaseRspDTO;
import com.sali.asyncollection.model.LabelDTO;
import com.sali.asyncollection.model.UserInfoDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.*;

/**
 * @description:
 * @author: sali
 * @date: 2024/8/27 上午9:27.
 * @version: 1.0
 */
@RequestMapping("/admin/v1")
@RestController
@Slf4j
public class TestParallelApi01Controller {

    @GetMapping("/parallel/01")
    public JSONObject parallelController01() {
        long beginTime = System.currentTimeMillis();
        log.info("开始并行查询app首页信息");

        ExecutorService executor = Executors.newFixedThreadPool(10);
        CompletionService<BaseRspDTO<Object>> baseDTOCompletionService = new ExecutorCompletionService<BaseRspDTO<Object>>(executor);

        //查询用户信息任务
        Callable<BaseRspDTO<Object>> userInfoDTOCallableTask = () -> {
            UserInfoDTO userInfoDTO = getUserInfo();
            BaseRspDTO<Object> userBaseRspDTO = new BaseRspDTO<Object>();
            userBaseRspDTO.setKey("userInfoDTO");
            userBaseRspDTO.setData(userInfoDTO);
            return userBaseRspDTO;
        };

        //banner信息查询任务
        Callable<BaseRspDTO<Object>> bannerDTOCallableTask = () -> {
            BannerDTO bannerDTO = getBannerInfo();
            BaseRspDTO<Object> bannerBaseRspDTO = new BaseRspDTO<Object>();
            bannerBaseRspDTO.setKey("bannerDTO");
            bannerBaseRspDTO.setData(bannerDTO);
            return bannerBaseRspDTO;
        };

        //label信息查询任务
        Callable<BaseRspDTO<Object>> labelDTODTOCallableTask = () -> {
            LabelDTO labelDTO = getLabelInfo();
            BaseRspDTO<Object> labelBaseRspDTO = new BaseRspDTO<Object>();
            labelBaseRspDTO.setKey("labelDTO");
            labelBaseRspDTO.setData(labelDTO);
            return labelBaseRspDTO;
        };

        //提交用户信息任务
        baseDTOCompletionService.submit(userInfoDTOCallableTask);
        //提交banner信息任务
        baseDTOCompletionService.submit(bannerDTOCallableTask);
        //提交label信息任务
        baseDTOCompletionService.submit(labelDTODTOCallableTask);

        UserInfoDTO userInfoDTO = null;
        BannerDTO bannerDTO = null;
        LabelDTO labelDTO = null;

        try {
            //因为提交了3个任务，所以获取结果次数是3
            CountDownLatch countDownLatch = new CountDownLatch(3);
            for (int i = 0; i < 3; i++) {
                Future<BaseRspDTO<Object>> baseRspDTOFuture = baseDTOCompletionService.poll(1, TimeUnit.MINUTES);
                BaseRspDTO baseRspDTO = baseRspDTOFuture.get();
                if ("userInfoDTO".equals(baseRspDTO.getKey())) {
                    userInfoDTO = (UserInfoDTO) baseRspDTO.getData();
                    countDownLatch.countDown();
                } else if ("bannerDTO".equals(baseRspDTO.getKey())) {
                    bannerDTO = (BannerDTO) baseRspDTO.getData();
                    countDownLatch.countDown();
                } else if ("labelDTO".equals(baseRspDTO.getKey())) {
                    labelDTO = (LabelDTO) baseRspDTO.getData();
                    countDownLatch.countDown();
                }
            }
            countDownLatch.await();
        } catch (Exception e) {
            e.printStackTrace();
        }

        log.info("结束并行查询app首页信息,总耗时：" + (System.currentTimeMillis() - beginTime));

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("userInfoDTO", userInfoDTO);
        jsonObject.put("bannerDTO", bannerDTO);
        jsonObject.put("labelDTO", labelDTO);

        return jsonObject;
    }

    private static UserInfoDTO getUserInfo() {
        try {
            log.info("getUserInfo正在执行...");
            Thread.sleep(100);
        } catch (InterruptedException ignored) {
        }
        return UserInfoDTO.builder().id(1L).username("username-A").build();
    }

    private static BannerDTO getBannerInfo() {
        try {
            log.info("getBannerInfo正在执行...");
            Thread.sleep(200);
        } catch (InterruptedException ignored) {
        }
        return BannerDTO.builder().id(1L).bannername("bannername-A").build();
    }

    private static LabelDTO getLabelInfo() {
        try {
            log.info("getLabelInfo正在执行...");
            Thread.sleep(300);
        } catch (InterruptedException ignored) {
        }
        return LabelDTO.builder().id(1L).labelname("labelname-A").build();
    }

    private static void printResult(UserInfoDTO userInfoDTO, BannerDTO bannerDTO, LabelDTO labelDTO) {
        log.info("userInfoDTO -> {}", userInfoDTO);
        log.info("bannerDTO -> {}", bannerDTO);
        log.info("labelDTO -> {}", labelDTO);
    }

}
